package com.example.framework;

import com.example.utils.SortedListOf;
import org.openqa.selenium.By;
import org.openqa.selenium.WebElement;

import java.util.List;

/**
 * Class manipulate with Groups Page
 */
public class GroupHelper extends WebDriverHelper {

    private SortedListOf<GroupData> cachedGroups;

    public GroupHelper(HelperManager manager) {
        super(manager);
    }

    public void createNewGroup(GroupData group) {
        manager.getNavigationHelper().gotoGroupsPage();
        initGroupCreation();
        fillGroupFields(group);
        submitGroupCreation();
        returnToGroupPage();
        rebuildCache();
    }

    public void modifyGroupByIndex(int groupIndex, GroupData groupData){
        manager.getNavigationHelper().gotoGroupsPage();
        selectGroupByIndex(groupIndex);
        initGroupModification();
        fillGroupFields(groupData);
        submitGroupModification();
        returnToGroupPage();
        rebuildCache();
    }

    /*
    Index should be 0-based index.
    That is you need to delete the first group index should be = 0.
    */
    public void deleteGroupByIndex(int index) {
        manager.getNavigationHelper().gotoGroupsPage();
        selectGroupByIndex(index);
        submitRemoving();
        returnToGroupPage();
        rebuildCache();
    }

    public SortedListOf<GroupData> getGroups() {
        if (cachedGroups == null){
            rebuildCache();
        }
        return cachedGroups;
    }

    private void rebuildCache(){
        cachedGroups = new SortedListOf<GroupData>();
        manager.getNavigationHelper().gotoGroupsPage();
        List<WebElement> groupsFromUI = driver.findElements(By.cssSelector("input[name='selected[]']"));
        for (WebElement groupFromUI : groupsFromUI){
            String groupName = getGroupNameFromUI(groupFromUI);
            cachedGroups.add(new GroupData().withName(groupName));
        }
    }

    /*
     Index should be 0-based index.
     That is you need to select the first group index should be = 0.
     */
    public GroupHelper selectGroupByIndex(int index) {
        manager.getNavigationHelper().gotoGroupsPage();
        click(getGroupByIndexLocator(index));
        return this;
    }

    private By getGroupByIndexLocator(int index) {
        return By.cssSelector("input[name='selected[]']:nth-of-type(" + (index + 1) + ")");
    }

    public GroupData getGroupByIndex(int index){
        manager.getNavigationHelper().gotoGroupsPage();
        WebElement groupFromUI = driver.findElement(getGroupByIndexLocator(index));
        String groupName = getGroupNameFromUI(groupFromUI);
        return new GroupData().withName(groupName);
    }

    private String getGroupNameFromUI(WebElement group) {
        String title = group.getAttribute("title");
        return title.substring("Select (".length(), title.length() - ")".length());
    }

    public GroupHelper submitRemoving() {
        click(By.name("delete"));
        returnToGroupPage();
        rebuildCache();
        return this;
    }

    //-------------------------------------------
    // Internal methods
    private GroupHelper returnToGroupPage() {
        if (driver.getCurrentUrl().contains("group.php")
                && driver.findElements(By.linkText("group page")).size() > 0) {
            click(By.linkText("group page"));
        }
        return this;
    }

    private void submitGroupCreation() {
        click(By.name("submit"));
        cachedGroups = null;
    }

    private void initGroupCreation() {
        click(By.name("new"));
    }

    private GroupHelper initGroupModification() {
        click(By.name("edit"));
        return this;
    }

    private GroupHelper submitGroupModification() {
        click(By.name("update"));
        cachedGroups = null;
        return this;
    }

    private GroupHelper fillGroupFields(GroupData group) {
        inputTextToEditBox(By.name("group_name"), group.getName());
        inputTextToEditBox(By.name("group_header"), group.getHeader());
        inputTextToEditBox(By.name("group_footer"), group.getFooter());
        return this;
    }
}
